﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;

namespace iWare.Wms.Application
{
    /// <summary>
    /// 出入明细服务
    /// </summary>
    [Route("api/AccessRecord")]
    [ApiDescriptionSettings("出入明细", Name = "AccessRecord", Order = 111)]

    public class AccessRecordService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WareDictData, MasterDbContextLocator> _wareDictDataRep; //仓库字典值仓储
        private readonly IRepository<WareArea, MasterDbContextLocator> _wareAreaRep; //所属库区仓储
        private readonly IRepository<PurchaseOrder, MasterDbContextLocator> _purchaseOrderRep; //采购订单仓储
        private readonly IRepository<GoodsDelivery, MasterDbContextLocator> _goodsDeliveryRep; //送货单仓储
        private readonly IRepository<v_accessrecord, MasterDbContextLocator> _v_accessrecord; //出入库明细试图仓储
        private readonly IRepository<WareLocation, MasterDbContextLocator> _wareLocationRep; //库位仓储

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareDictDataRep"></param>
        /// <param name="wareAreaRep"></param>
        /// <param name="purchaseOrderRep"></param>
        /// <param name="goodsDeliveryRep"></param>
        /// <param name="v_accessrecord"></param>
        /// <param name="wareLocationRep"></param>
        public AccessRecordService(
            IRepository<WareDictData, MasterDbContextLocator> wareDictDataRep,
            IRepository<WareArea, MasterDbContextLocator> wareAreaRep,
            IRepository<PurchaseOrder, MasterDbContextLocator> purchaseOrderRep,
            IRepository<GoodsDelivery, MasterDbContextLocator> goodsDeliveryRep,
            IRepository<v_accessrecord, MasterDbContextLocator> v_accessrecord,
            IRepository<WareLocation, MasterDbContextLocator> wareLocationRep
            )
        {
            _wareDictDataRep = wareDictDataRep;
            _wareAreaRep = wareAreaRep;
            _purchaseOrderRep = purchaseOrderRep;
            _goodsDeliveryRep = goodsDeliveryRep;
            _v_accessrecord = v_accessrecord;
            _wareLocationRep = wareLocationRep;
        }
        #endregion

        /// <summary>
        /// 分页查询出入明细
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("Page")]
        public async Task<PageResult<AccessRecordOutput>> Page([FromQuery] AccessRecordInput input)
        {
            var list = await _v_accessrecord.DetachedEntities
                .Where(input.TaskModel != TaskModel.ALL, u => u.TaskModel == input.TaskModel)
                .Where(input.TaskType != TaskType.All, u => u.TaskType == input.TaskType)
                .Where(input.TaskStatus != TaskStatusEnum.All, u => u.TaskStatus == input.TaskStatus)
                .Where(!string.IsNullOrEmpty(input.TaskNo), u => EF.Functions.Like(u.TaskNo, $"%{input.TaskNo.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.TaskContainerCode), u => EF.Functions.Like(u.TaskContainerCode, $"%{input.TaskContainerCode.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.ProjectCode), u => EF.Functions.Like(u.ProjectCode, $"%{input.ProjectCode.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.Code), u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.TaskCreatedUserName), u => EF.Functions.Like(u.TaskCreatedUserName, $"%{input.TaskCreatedUserName.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.SearchBeginTime), u => u.TaskCreatedTime >= DateTime.Parse(input.SearchBeginTime.Trim()) &&
                 u.TaskCreatedTime <= DateTime.Parse(input.SearchEndTime.Trim()))
                .OrderBy(u => u.TaskStatus)
                .ThenByDescending(u => u.TaskCreatedTime)
                .ThenByDescending(u => u.TaskUpdatedTime)
                .ProjectToType<AccessRecordOutput>()
                .ToADPagedListAsync(input.PageNo, input.PageSize);

            foreach (var item in list.Rows)
            {
                if (item.BindQuantity == null) item.BindQuantity = 1;
                item.ContainerCode = string.IsNullOrEmpty(item.ContainerCode) ? "N/A" : item.ContainerCode;
                item.ProjectCode = string.IsNullOrEmpty(item.ProjectCode) ? "N/A" : item.ProjectCode;
                item.Code = string.IsNullOrEmpty(item.Code) ? "N/A" : item.Code;
                item.Name = string.IsNullOrEmpty(item.Name) ? "N/A" : item.Name;
                item.SpecificationModel = string.IsNullOrEmpty(item.SpecificationModel) ? "N/A" : item.SpecificationModel;
                item.Unit = string.IsNullOrEmpty(item.Unit) ? "N/A" : item.Unit;
                item.BrandName = string.IsNullOrEmpty(item.BrandName) ? "N/A" : item.BrandName;
                item.Unit = string.IsNullOrEmpty(item.Unit) ? "N/A" : item.Unit;
                item.XuHao = string.IsNullOrEmpty(item.XuHao) ? "N/A" : item.XuHao;

                var goodsDelivery = await _goodsDeliveryRep.FirstOrDefaultAsync(z => z.DeliveryNo == item.DeliveryNo);
                if (goodsDelivery != null)
                {
                    item.DeliveryNo = goodsDelivery.DeliveryNo;
                    var purchaseOrder = await _purchaseOrderRep.FirstOrDefaultAsync(t => t.PurchaseNo == item.PurchaseNo && t.PurchaseType == goodsDelivery.DeliveryType);
                    item.PurchaseNo = purchaseOrder != null && purchaseOrder.IsJiaJiJian == YesOrNot.Y ? "" : item.PurchaseNo;
                    item.PurchaseTypeName = (await _wareDictDataRep.DetachedEntities.Where(z => z.TypeId == 313570112090181 && z.Code == goodsDelivery.DeliveryType).FirstOrDefaultAsync()).Value;
                }
                else
                {
                    item.PurchaseNo = "N/A";
                    item.PurchaseTypeName = "N/A";
                    item.DeliveryNo = "N/A";
                }

                var areaID = new long(); //定义所属库区

                if (item.TaskType == TaskType.In) //入库任务
                {
                    var wareLocation = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == item.ToLocationCode);
                    if (wareLocation != null) { areaID = wareLocation.AreaID; }
                }
                else if (item.TaskType == TaskType.Out) //出库任务
                {
                    var wareLocation = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == item.FromLocationCode);
                    if (wareLocation != null) { areaID = wareLocation.AreaID; }
                }
                else areaID = 0;

                // 查询所属库区
                var wareArea = await _wareAreaRep.FirstOrDefaultAsync(z => z.Id == areaID);
                item.ReservoirArea = wareArea != null ? wareArea.AreaName : "";
            }

            return list;
        }

        /// <summary>
        /// 打印和导出出入明细
        /// </summary>
        /// <returns></returns>
        public async Task<List<AccessRecordOutput>> List([FromQuery] AccessRecordListInput input)
        {
            var list = await _v_accessrecord.DetachedEntities
                  .Where(input.TaskModel != TaskModel.ALL, u => u.TaskModel == input.TaskModel)
                  .Where(input.TaskType != TaskType.All, u => u.TaskType == input.TaskType)
                  .Where(input.TaskStatus != TaskStatusEnum.All, u => u.TaskStatus == input.TaskStatus)
                  .Where(!string.IsNullOrEmpty(input.TaskNo), u => EF.Functions.Like(u.TaskNo, $"{input.TaskNo.Trim()}"))
                  .Where(!string.IsNullOrEmpty(input.TaskContainerCode), u => EF.Functions.Like(u.TaskContainerCode, $"{input.TaskContainerCode.Trim()}"))
                  .Where(!string.IsNullOrEmpty(input.ProjectCode), u => EF.Functions.Like(u.ProjectCode, $"{input.ProjectCode.Trim()}"))
                  .Where(!string.IsNullOrEmpty(input.Code), u => EF.Functions.Like(u.Code, $"{input.Code.Trim()}"))
                  .Where(!string.IsNullOrEmpty(input.SearchBeginTime), u => u.TaskCreatedTime >= DateTime.Parse(input.SearchBeginTime.Trim()) &&
                   u.TaskCreatedTime <= DateTime.Parse(input.SearchEndTime.Trim()))
                  .OrderBy(z => z.TaskStatus)
                  .OrderByDescending(z => z.TaskCreatedTime)
                  .ProjectToType<AccessRecordOutput>().ToListAsync();

            foreach (var item in list)
            {
                if (item.BindQuantity == null) item.BindQuantity = 1;
                item.ContainerCode = string.IsNullOrEmpty(item.ContainerCode) ? "N/A" : item.ContainerCode;
                item.ProjectCode = string.IsNullOrEmpty(item.ProjectCode) ? "N/A" : item.ProjectCode;
                item.Code = string.IsNullOrEmpty(item.Code) ? "N/A" : item.Code;
                item.Name = string.IsNullOrEmpty(item.Name) ? "N/A" : item.Name;
                item.SpecificationModel = string.IsNullOrEmpty(item.SpecificationModel) ? "N/A" : item.SpecificationModel;
                item.Unit = string.IsNullOrEmpty(item.Unit) ? "N/A" : item.Unit;
                item.BrandName = string.IsNullOrEmpty(item.BrandName) ? "N/A" : item.BrandName;
                item.Unit = string.IsNullOrEmpty(item.Unit) ? "N/A" : item.Unit;
                item.XuHao = string.IsNullOrEmpty(item.XuHao) ? "N/A" : item.XuHao;
            }

            return list;
        }
    }
}
